home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / procssng / popi / popi.lha / popi / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-15  |  16.0 KB  |  555 lines

  1.  
  2. /*  @(#)main.c 1.5 92/04/16
  3.  *
  4.  *  Main routine and declarations used by the popi program.
  5.  *
  6.  *  Popi was originally written by Gerard J. Holzmann - AT&T Bell Labs.
  7.  *  This version is based on the code in his Prentice Hall book,
  8.  *  "Beyond Photography - the digital darkroom," ISBN 0-13-074410-7,
  9.  *  which is copyright (c) 1988 by Bell Telephone Laboratories, Inc. 
  10.  *
  11.  *  Permission is given to distribute these extensions, as long as these
  12.  *  introductory messages are not removed, and no monies are exchanged.
  13.  *
  14.  *  No responsibility is taken for any errors or inaccuracies inherent
  15.  *  either to the comments or the code of this program, but if reported
  16.  *  (see README file) then an attempt will be made to fix them.
  17.  */
  18.  
  19.  
  20. #include <stdio.h>
  21. #include <setjmp.h>
  22. #include <ctype.h>
  23. #include "popi.h"
  24. #include "expr.h"
  25. #include "patchlevel.h"
  26.  
  27. /* Prototypes for local functions */
  28.  
  29. static void do_parse    P((FILE *)) ;
  30. static void doit        P((Tree *)) ;
  31. static void get_options P((int, char **[])) ;
  32. static void Usage       P((int)) ;
  33. int main                P((int, char **)) ;
  34.  
  35. struct SRC Images[MAXIMG] ;     /* Array of images. */
  36. struct SRC *CurOld ;            /* Pointer to "old" image */
  37. struct SRC *CurNew ;            /* Pointer to "new" image */
  38.  
  39. pixel_t *ntsc = NULL ;          /* NTSC luma line. */
  40. pixel_t Zmax = DEF_ZSIZE - 1 ;  /* Max brightness level */
  41.  
  42. FILE *Debug = NULL ;            /* Debugging output stream */
  43. FILE *InputStream = (FILE *) 0 ;
  44. FILE *LogStr = NULL ;           /* Logging output stream */
  45.  
  46. /* One level of character pushback on stdin to avoid disp_ungetc() */
  47.  
  48. char  SaveChar = '\0' ;
  49.  
  50. char ErrBuf[256] ;
  51. char lastfname[MAXPATHLEN] ;    /* Last filename parsed. */
  52. char lastimage[MAXPATHLEN] ;    /* Last image name parsed. */
  53. char *ProgName ;                /* Program name (for err messages) */
  54. char *LogFile = "popi.log" ;    /* Name of log file */
  55. char geometry[MAXLINE] ;        /* X11 geometry information. */
  56. char x11_display[MAXLINE] ;     /* X11 display information. */
  57.  
  58. enum disp_type dtype = IS_COLOR ;      /* Display in (color/gray/mono). */
  59. enum rng_type rng_policy = CUT ;       /* Range error handling. */
  60.  
  61. int noerr = TRUE ;
  62. int BOXW ;                      /* Text box width */
  63. int TXsize ;                    /* Total width */
  64. int TYsize ;                    /* Total height */
  65. int Xsize = DEF_X ;             /* Image width */
  66. int Ysize = DEF_Y ;             /* Image height */
  67. int Zsize = DEF_ZSIZE ;         /* No. brightness levels */
  68. int Xoffset = 0 ;        /* x offset from corner of screen */
  69. int Yoffset = 0 ;        /* y offset from corner of screen */
  70. int OverlayFlag = FALSE ;    /* don't clear screen if true */
  71. int RangeCheck = 1 ;
  72. int disp_active = 1 ;           /* So we can turn off the display */
  73. int CharPos = 0 ;               /* Current character position on input line */
  74. int HaveToken = 0 ;             /* Set when one (or more) tokens parsed. */
  75. int OldPos = 0 ;                /* Previous character position on input line */
  76. int TokPos = 0 ;                /* Position of beginning of current token */
  77. int colors = 1 ;                /* RGB color mode (default off) */
  78. int rev_video = 0 ;             /* Set if monochrome reverse video. */
  79. int signed_io = 0 ;             /* Signed I/O mode (default off) */
  80. int Truncate = 0 ;              /* Truncate assignments instead of wrapping. */
  81. int Verbose = 0 ;               /* Be chatty */
  82. int iconic = 0 ;                /* Set if the window is in an iconic state. */
  83. int oldfmt = 0 ;                /* Set to save images in old format. */
  84. int prs = 0 ;
  85. int tcache = 0 ;                /* Set to read/write cached trig info. */
  86. int saw_eof = 0 ;
  87. int scr_depth = 1 ;             /* Screen depth (where appropriate). */
  88. int col_used = 0 ;        /* colors used in current computation. */
  89.  
  90. parse_t parsed[MAXTOKENS] ;
  91.  
  92. Tree *tree ;
  93.  
  94. static jmp_buf jb ;
  95.  
  96. #if       SEQPAR
  97. int ncpus = 1 ;                 /* Default is single-tasking */
  98. #endif /* SEQPAR */
  99.  
  100. static char *UsageMsg[] = {
  101.   "\nvalid options:",
  102.   "  -a[+-]       turn auto-display on (off)",
  103.   "  -C           display in color",
  104.   "  -D[file]     enable debugging trace (default stderr)",
  105.   "  -d disp      specify X11 display",
  106.   "  -G           display in grayscale",
  107.   "  -g geom      specify X11 geometry",
  108.   "  -i           start window iconically",
  109.   "  -l[file]     log all commands (default ./popi.log)",
  110.   "  -M           display in monochrome",
  111.   "  -o           save images to disk in old popi format",
  112.   "  -p#          specify number of CPUs (if available)",
  113.   "  -r[+-]       turn range checking on (off)",
  114.   "  -s[+-]       turn signed I/O mode on (off)",
  115.   "  -t[+-]       turn trig caching mode on (off)",
  116.   "  -V           print version number",
  117.   "  -v[+-]       turn verbose mode on (off)",
  118.   "  -xWidth      specify initial image width (in pixels)",
  119.   "  -yHeight     specify initial image height (in scanlines)",
  120.   "  -zDepth      specify image depth (in levels)",
  121.   (char *) 0
  122. } ;
  123.  
  124.  
  125. void
  126. PrStrs(msg)
  127. char *msg[] ;
  128. {
  129.   char **p ;
  130.  
  131.   for (p = msg; *p; ++p) FPRINTF(stderr, "%s\n", *p) ;
  132. }
  133.  
  134.  
  135. static void
  136. Usage(status)
  137. int status ;
  138. {
  139.   FPRINTF(stderr, "Usage: %s [options] [image-files]\n", ProgName) ;
  140.   PrStrs(UsageMsg) ;
  141.  
  142. /* Also need a driver-specific usage message appended. */
  143.  
  144.   exit(status) ;
  145. }
  146.  
  147.  
  148. void
  149. version()
  150. {
  151. #if defined(ISTACK)
  152.   FPRINTF(stderr, "%s: (integer) version 3.2.%1d\n",
  153.           ProgName, PATCHLEVEL) ;
  154. #else
  155.   FPRINTF(stderr, "%s: (floating point) version 3.2.%1d\n",
  156.           ProgName, PATCHLEVEL) ;
  157. #endif /*ISTACK*/
  158. }
  159.  
  160.  
  161. static void
  162. get_options(argc, argvp)           /* Read command line options. */
  163. int argc ;
  164. char **argvp[] ;
  165. {
  166.   extern int yydebug ;
  167.   char **argv ;
  168.   char **new_argv ;
  169.   char **nav ;
  170.  
  171.   argv = *argvp ;
  172.   new_argv = (char **)
  173.              LINT_CAST(Emalloc((unsigned) ((argc + 1) * sizeof (char *)))) ;
  174.   nav = new_argv ;
  175.   for (ProgName = *nav++ = *argv++; *argv && **argv == '-'; ++argv)
  176.     {
  177.       bool ArgRecognised ;
  178.  
  179.       ArgRecognised = TRUE ;
  180.       switch (*++*argv)
  181.         {
  182.           case 'a' : if (*++*argv == '-')     /* Auto-display */
  183.                        disp_active = 0 ;
  184.                      else
  185.                        disp_active = 1 ;
  186.                      break ;
  187.  
  188.           case 'C' : dtype = IS_COLOR ;       /* Display in color. */
  189.                      break ;
  190.  
  191.           case 'D' : if (*++*argv)
  192.                        {
  193.                          if ((Debug = fopen(*argv, "w")) == NULL)
  194.                            {
  195.                              SPRINTF(ErrBuf,
  196.                               "Can't open debug file '%s' - using stderr",
  197.                               *argv) ;
  198.                              error(ERR_SYS) ;
  199.                              Debug = stderr ;
  200.                            }
  201.                        }    
  202.                      else Debug = stderr ;
  203.                      setbuf(Debug, (char *) NULL) ;    /**/
  204.                      yydebug = 1 ;
  205.                      break ;
  206.  
  207.           case 'd' : ++argv ;                 /* X11 display information. */
  208.                      if (*argv == NULL)
  209.                        Usage(0) ;               /* Print usage message */
  210.                        /*NOTREACHED*/
  211.                      STRCPY(x11_display, *argv) ;
  212.                      break ;
  213.  
  214.           case 'G' : dtype = IS_GRAY ;        /* Display in grayscale. */
  215.                      break ;
  216.  
  217.           case 'g' : ++argv ;                 /* X11 geometry information. */
  218.                      if (*argv == NULL)
  219.                        Usage(0) ;               /* Print usage message */
  220.                        /*NOTREACHED*/
  221.                      STRCPY(geometry, *argv) ;
  222.                      break ;
  223.  
  224.           case 'i' : iconic = 1 ;             /* Start window iconically. */
  225.                      break ;
  226.  
  227.           case 'l' : if (*++*argv)            /* Log all commands */
  228.                        LogFile = *argv ;
  229.                      OpenLog(&LogStr) ;
  230.                      break ;
  231.  
  232.           case 'M' : dtype = IS_MONO ;        /* Display in monochrome. */
  233.                      break ;
  234.  
  235.           case 'o' : oldfmt = 1 ;             /* Save images in old format. */
  236.                      break ;
  237.  
  238.           case 'p' :                          /* No. cpus to use in parallel */
  239.  
  240.           /*  Still recognise the option on other machines,
  241.        *  so scripts can use this option portably.
  242.            */
  243.  
  244. #if       SEQPAR
  245.                      if (*++*argv)
  246.                        {
  247.                          ncpus = atoi(*argv) ;
  248.                          if (ncpus >= cpus_online()) ncpus = cpus_online() - 1 ;
  249.                          if (ncpus < 0) ncpus = 0 ;
  250.                        }
  251.                      else ncpus = cpus_online() - 1 ;
  252. #endif /* SEQPAR */
  253.  
  254.                      break ;
  255.  
  256.           case 'r' : if (*++*argv == '-')     /* Range checking */
  257.                        RangeCheck = 0 ;
  258.                      else
  259.                        RangeCheck = 1 ;
  260.                      break ;
  261.  
  262.           case 's' : if (*++*argv == '-')     /* Signed I/O mode */
  263.                        signed_io = 0 ;
  264.                      else
  265.                        signed_io = 1 ;
  266.                      break ;
  267.  
  268.           case 't' : if (*++*argv == '-')     /* Trig caching mode */
  269.                        tcache = 0 ;
  270.                      else
  271.                        tcache = 1 ;
  272.                      break ;
  273.  
  274.           case 'V' : version() ;              /* Print version number. */
  275.                      exit(0) ;
  276.                      /*NOTREACHED*/
  277.  
  278.           case 'v' : if (*++*argv == '-')     /* Verbose */
  279.                        Verbose = 0 ;
  280.                      else
  281.                        ++Verbose ;
  282.                      break ;
  283.  
  284.           case 'x' : Xsize = atoi(++*argv) ;
  285.                      break ;
  286.  
  287.           case 'y' : Ysize = atoi(++*argv) ;
  288.                      break ;
  289.  
  290.           case 'z' : Zsize = atoi(++*argv) ;
  291.                      Zmax = (pixel_t) (Zsize - 1) ;
  292.                      break ;
  293.  
  294.           case 'X' : Xoffset = atoi(++*argv) ;
  295.                      break ;
  296.  
  297.           case 'Y' : Yoffset = atoi(++*argv) ;
  298.                      break ;
  299.  
  300.       case 'O' : OverlayFlag = TRUE ;
  301.              break ;
  302.  
  303.           case '?' : Usage(0) ;               /* Print usage message */
  304.                      /*NOTREACHED*/
  305.  
  306. /*  Note: no error on default because drivers may interpret other options.
  307.  *  It's up to them to give an error message if they can.
  308.  */
  309.  
  310.           default  : ArgRecognised = FALSE ;
  311.         }
  312.  
  313.       if (!ArgRecognised) *nav++ = *argv ;
  314.     }
  315.   *nav = (char *) 0 ;
  316.  
  317.   CurOld          = &Images[0] ;          /* Create initial "old" image. */
  318.   CurOld->pix     = ImgAlloc(Xsize, Ysize, colors) ;
  319.   CurOld->str     = Emalloc((unsigned int) (strlen("old")+1)) ;
  320.   STRCPY(CurOld->str, "old") ;
  321.   CurOld->width   = Xsize ;
  322.   CurOld->height  = Ysize ;
  323.   CurOld->ncolors = colors ;
  324.   CurOld->Xalloc  = Xsize ;
  325.  
  326.   CurNew          = &Images[1] ;          /* Create initial "new" image. */
  327.   CurNew->pix     = ImgAlloc(Xsize, Ysize, colors) ;
  328.   CurNew->str     = Emalloc((unsigned int) (strlen("new")+1)) ;
  329.   STRCPY(CurNew->str, "new") ;
  330.   CurNew->width   = Xsize ;
  331.   CurNew->height  = Ysize ;
  332.   CurNew->ncolors = colors ;
  333.   CurNew->Xalloc  = Xsize ;
  334.  
  335.   for (; *argv; ++argv) getpix(*argv, (char *) 0, FALSE) ;
  336.  
  337.   if (colors == 3)
  338.     ntsc = (pixel_t *) Emalloc((unsigned) Xsize * sizeof(pixel_t)) ;
  339. }
  340.  
  341.  
  342. /*  We deliberately don't exit on error here.
  343.  *  The user may have some picture that has taken ages to develop.
  344.  *  If we run out of memory, they have a chance to save the image and
  345.  *  exit themselves, which they should do as soon as possible.
  346.  */
  347.  
  348. char *
  349. Emalloc(n)
  350. unsigned int n ;
  351. {
  352.   char *try ;
  353.   static unsigned long TotalAllocated = 0L ;
  354.  
  355.   if ((try = malloc(n)) == NULL)
  356.     {
  357.       SPRINTF(ErrBuf, "Allocate %u bytes failed (total malloc=%ld",
  358.                       n, TotalAllocated) ;
  359.       error(ERR_SYS) ;
  360.     }
  361.   CLEARMEM(try, (int) n) ;
  362.   TotalAllocated += n ;
  363.   return(try) ;
  364. }
  365.  
  366.  
  367. void
  368. Quit()
  369. {
  370.   disp_finish() ;
  371.   exit(0) ;
  372. }
  373.  
  374.  
  375. main(argc, argv)
  376. int argc ;
  377. char **argv ;
  378. {
  379.   get_options(argc, &argv) ;          /* read the command line options. */
  380.   TXsize = Xsize ;
  381.   if (TXsize < TWIDTH) TXsize = TWIDTH ;
  382.   TYsize = Ysize+100 ;
  383.   BOXW   = TXsize-50 ;
  384.  
  385.   disp_init(argc, argv) ;
  386.  
  387. #if       SEQPAR
  388.   m_set_procs(ncpus) ;
  389. #endif /* SEQPAR */
  390.  
  391.   setjmp(jb) ;
  392.   do_parse((FILE *) 0) ;
  393.   Quit() ;
  394.  
  395.   return 0 ;         /* Shut up warning messages from some compilers */
  396. /*NOTREACHED*/
  397. }
  398.  
  399.  
  400. static void
  401. do_parse(istr)
  402. FILE *istr ;
  403. {
  404.   FILE *SaveInput ;    /* Saved previous input stream. */
  405.  
  406. /* Save and then reset current input stream. */
  407.  
  408.   SaveInput = InputStream ;
  409.   InputStream = istr ;
  410.  
  411.   for (;;)
  412.     {
  413.       DEBUG((Debug, "do_parse() - top of loop\n")) ;
  414.       noerr = TRUE ;
  415.  
  416. /* Display popi prompt and clear input line. Returns length of popi prompt. */
  417.  
  418.       CharPos = (istr) ? 0 : disp_prompt() ;
  419.       HaveToken = 0 ;
  420.  
  421.       if (LogStr)
  422.         {
  423.           FPRINTF(LogStr, "-> ") ;
  424.           FFLUSH(LogStr) ;
  425.         } 
  426.  
  427.       yyparse() ;
  428.       if (saw_eof) break ;
  429.       col_used = 0 ;
  430.       if (noerr && tree != NULL) doit(tree) ;
  431.       afree() ;
  432.     } 
  433.  
  434. /* Restore saved previous input stream. */
  435.  
  436.   InputStream = SaveInput ;
  437. }
  438.  
  439.  
  440. static void
  441. doit(t)
  442. Tree *t ;
  443. {
  444.   switch (t->t)
  445.     {
  446.       case T_Color   : setcolor() ;
  447.                        break ;
  448.       case T_Comb    : combine(t) ;
  449.                        break ;
  450.       case T_Debug   : debug(t) ;
  451.                        break ;
  452.       case T_Display : displayimg(t) ;
  453.                        break ;
  454.       case T_Explo   : explode(t) ;
  455.                        break ;
  456.       case T_Free    : freeimg(t) ;
  457.                        break ;
  458.       case T_Genep   : genepson(t) ;
  459.                        break ;
  460.       case T_Genps   : genps(t) ;
  461.                        break ;
  462.       case T_Get     : getputrgb(t, TRUE) ;
  463.                        break ;
  464.       case T_Gray    : setgray() ;
  465.                        break ;
  466.       case T_Help    : help() ;
  467.                        break ;
  468.       case T_List    : showfiles() ;
  469.                        break ;
  470.       case T_Logfile : dolog(t) ;
  471.                        break ;
  472.       case T_Luma    : luma(t) ;
  473.                        break ;
  474.       case T_Matte   : matte(t) ;
  475.                        break ;
  476.       case T_Melt    : melt(t) ;
  477.                        break ;
  478.       case T_Mono    : setmono() ;
  479.                        break ;
  480.       case T_Ofmt    : ofmt(t) ;
  481.                        break ;
  482.       case T_Oil     : oil(t) ;
  483.                        break ;
  484.       case T_Put     : getputrgb(t, FALSE) ;
  485.                break ;
  486.       case T_Quit    : Quit() ;
  487.                        break ;
  488.       case T_Range   : dorange(t) ;
  489.                break ;
  490.       case T_Read    : readimg(t) ;
  491.                        break ;
  492.       case T_Shear   : shear(t) ;
  493.                        break ;
  494.       case T_Signed  : dosigned(t) ;
  495.                        break ;
  496.       case T_Size    : dosize(t) ;
  497.                break ;
  498.       case T_Slice   : slice(t) ;
  499.                        break ;
  500.       case T_Store   : stopict(t, -1, "") ;
  501.                        break ;
  502.       case T_Tile    : tile(t) ;
  503.                        break ;
  504.       case T_Trunc   : imtrunc(t) ;
  505.                        break ;
  506.       case T_Undo    : undo() ;
  507.                        break ;
  508.       case T_Verbose : verbose(t) ;
  509.                        break ;
  510.       case T_Ver     : version() ;
  511.                        break ;
  512.       case T_Write   : writeimg(t) ;
  513.                        break ;
  514.       default        : compile(t) ;
  515.     }
  516. }
  517.  
  518.  
  519. void
  520. error(errtype)
  521. int errtype ;
  522. {
  523.   DEBUG((Debug, "error: type %d, pos %d msg '%s'\n",
  524.                  errtype, TokPos, ErrBuf)) ;
  525.   if (!noerr) return ;                        /* Already printed a message */
  526.   disp_error(errtype, TokPos) ;
  527.   noerr = FALSE ;                             /* An error has occurred */
  528.  
  529.   if (LogStr) FPRINTF(LogStr, "Error: %s\n", ErrBuf) ;
  530. }
  531.  
  532.  
  533. void
  534. run_error(errtype)
  535. int errtype ;
  536. {
  537.   DEBUG((Debug, "Run error: type %d, pos %d msg '%s'\n",
  538.                  errtype, TokPos, ErrBuf)) ;
  539.   disp_error(errtype, TokPos) ;
  540.   if (LogStr) FPRINTF(LogStr, "Run error: %s\n", ErrBuf) ;
  541.   longjmp(jb, 1) ;
  542. }
  543.  
  544.  
  545. int
  546. getImageNo(name)
  547. char *name ;
  548. {
  549.   int i ;
  550.  
  551.   for (i = 0; i < nimages; i++)
  552.     if (strcmp(Images[i].str, name) == 0) return(i) ;
  553.   return(-1) ;
  554. }
  555.